<template>
  <div class="gnb-list flex-column h100p "
       style="background-color: #fafafa;"
       onselectstart="return false"
  >
    <div class="flex-horiz flex-not-shk pa-sm">
      <el-button-group>
        <el-button class="el-icon-back"
                   :disabled="folderStack.length < 2 "
                   @click="onClickBack"
        ></el-button>
        <el-button icon="el-icon-folder-add"
                   @click="addItem(false)"
        >文件夹
        </el-button>
        <el-button icon="el-icon-document-add"
                   @click="addItem(true)"
        >文件
        </el-button>
      </el-button-group>
    </div>
    <div class="flex-not-shk pa-sm flex-horiz flex-center"
         v-if="addItemStatus"
    >
      <el-input
          :placeholder="`请输入${addItemStatus === 1 ? '文件名' : '文件夹'}`"
          v-gnb-autofocus
          @blur="addItemStatus = 0"
          @keydown.enter="onPassEnter"
          v-model="fileOrFoldName"
      >
        <template #prefix>
          <i class="el-input__icon el-icon-document-add "
             v-if="addItemStatus === 1"
          ></i>
          <i class="el-input__icon el-icon-folder-add "
             v-if="addItemStatus === 2"
          ></i>
        </template>
      </el-input>
    </div>
    <div class="flex-grow h0">
      <div class="cursor-d list-line ptb-sm plr-sm color-text flex-horiz flex-center"
           v-for="item in itemList"
           :class="( selectedItem && selectedItem.key === item.key ) ? 'bg-border active' : ''"
           @mousedown.left="(e)=>onMouseDown(e,item)"
           @mouseup.left="(e)=>onMouseUp(e, item)"
           @mouseup.right="e => onMouseDownRight(e,item)"
           @dblclick="onDblCLick(item)"
           @click="onClickItem(item)"
      >
        <div class="mr-sm" v-if="!item.isFile"><i class="el-icon-folder"></i></div>
        <div v-if="renameTarget !== item">{{ item.name }}</div>
        <div class="" v-else>
          <el-input v-model="renameTarget.rename"
                    v-gnb-autofocus
                    @keydown.enter="onPressEnterRename(item)"
                    @blur="renameTarget = null"
          ></el-input>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import {useStore} from "vuex";
import {computed, onBeforeUnmount, reactive, ref, toRaw, toRefs, watch, onMounted, getCurrentInstance} from "vue";
import {IpcRenderer} from "@/utils/render/common";
import {PATTERN_FILE_NAME, validatePattern} from "@/utils/pattern.utils";
import {ElMessage} from "element-plus";
import {DirTree} from "@/utils/main/file.uitls";
import {debounce} from "@/utils/throttle-debounce.utils";
import {CommonListener} from "@/utils/listener.utils";

export default {
  name: 'gnb-list',
  mixins: [],
  components: {},
  props: {
    data: {
      default: () => ([])
    }
  },
  data() {
    return {}
  },
  setup(props, ctx) {
    const instance = getCurrentInstance();
    const store = useStore();

    const onMouseDown = (e, item) => {
      store.dispatch("setSource", item);
    }

    const onMouseUp = (e, item) => {
      const {source} = store.state.drag;
      if (item === source) return;
      store.dispatch("setTarget", item);
    }

    const folderStack = ref([]);
    const selectedFolder = computed(() => store.state.note.selectedFolder);
    if (selectedFolder) folderStack.value.push(selectedFolder);

    let lastSelectedFolderKey = '';

    const selectedFolderChangeHandler = (v) => {
      if (!v) return folderStack.value = [];
      if (v.key === lastSelectedFolderKey) return refreshList();
      folderStack.value = [v];
      lastSelectedFolderKey = v.key;
    }

    watch(selectedFolder, selectedFolderChangeHandler);

    onMounted(() => selectedFolderChangeHandler(selectedFolder.value))

    const itemList = ref([]);

    const refreshList = async () => {
      const v = folderStack.value;
      if (!v.length) itemList.value = [];
      const f = v[v.length - 1];
      if (f) {
        const list = await IpcRenderer.invoke("getCurrentItems", f.path);
        itemList.value = list.sort((a, b) => {
          if (!a.isFile) return -1;
          if (!b.isFile) return 1;
          return b.modifiedTime - a.modifiedTime;
        });
      }
      await store.dispatch("setSelectedItem", null);
    }

    watch(folderStack, (v) => {
      refreshList();
    }, {deep: true})

    const onDblCLick = (item) => {
      if (!item.isFile) {
        folderStack.value.push(item);
      }
    }

    const onClickBack = () => {
      if (folderStack.value.length > 1) folderStack.value.pop();
    }

    const addItemStatus = ref(0);
    const fileOrFoldName = ref("");

    const addItem = (isFile) => {
      if (!folderStack.value.length) return;
      addItemStatus.value = isFile ? 1 : 2;
    }

    let waitSelectName = "";

    watch(itemList, (v) => {
      if (!waitSelectName) return;
      const selected = v.find(item => item.name === waitSelectName && item.isFile);
      if (selected) store.dispatch("setSelectedItem", selected);
      waitSelectName = '';
    }, {deep: true});

    const onPassEnter = async () => {
      if (addItemStatus.value === 0) return;
      let res = validatePattern(fileOrFoldName.value.trim(), PATTERN_FILE_NAME);
      if (res !== true) {
        return ElMessage.error(res as string);
      }
      const name = fileOrFoldName.value; // + (addItemStatus.value === 1 ? '.md' : '');
      const path = folderStack.value[folderStack.value.length - 1].path;
      const item = new DirTree(name, path + "/" + name, [], addItemStatus.value === 1);
      res = await IpcRenderer.invoke("addItem", item);
      if (res) {
        if (addItemStatus.value === 1) {
          waitSelectName = name;
          CommonListener.trigger("setEditMode", 1);
        }
        await refreshList();
        await store.dispatch("syncNoteDirectories");
      }
      addItemStatus.value = 0;
      fileOrFoldName.value = '';
    }

    const onClickItem = (item) => {
      if (!item.isFile) return;
      store.dispatch("setSelectedItem", item);
    }


    const menuTarget = ref(null);
    const onMouseDownRight = (e, item) => {
      e.preventDefault();
      menuTarget.value = item;
      CommonListener.trigger("showRightMenu", e, 'list', item);
    }

    const onClickMenuDelete = (item) => {
      if (item !== menuTarget.value) return;
      instance.proxy['$confirm'](`确认删除 < ${item.name} > ?`, '删除确认').then(async () => {
        const res = await IpcRenderer.invoke("deleteItem", toRaw(menuTarget.value));
        if (res) itemList.value = itemList.value.filter(item => item !== menuTarget.value);
      })
    }

    const renameTarget = ref(null);
    const onclickMenuRename = (item) => {
      if (item !== menuTarget.value) return;
      menuTarget.value.rename = menuTarget.value.name;
      renameTarget.value = menuTarget.value;
    }

    const removeRename = CommonListener.addListener("onClickListMenuRename", onclickMenuRename);
    const removeDelete = CommonListener.addListener("onClickListMenuDelete", onClickMenuDelete);
    const removeRefresh = CommonListener.addListener("onMoveItem", refreshList);

    onBeforeUnmount(() => {
      removeRename();
      removeDelete();
      removeRefresh();
    })


    const onPressEnterRename = async (item) => {
      waitSelectName = item.rename;
      const res = await IpcRenderer.invoke("renameItem", toRaw(item));
      await refreshList();
    }

    return {
      selectedFolder,
      itemList,
      folderStack,
      addItemStatus,
      fileOrFoldName,
      selectedItem: computed(() => store.state.note.selectedItem),
      renameTarget,


      onMouseDown,
      onMouseUp,
      onDblCLick,
      onClickBack,
      addItem,
      onPassEnter,
      onClickItem,
      onMouseDownRight,
      onPressEnterRename,
    }
  },
  computed: {},
  watch: {},
  created() {
  },
  mounted() {
  },
  beforeUnmount() {
  },
  activated() {
  },
  deactivated() {
  },
  methods: {}
};
</script>

<style scoped lang="less">
.gnb-list {

}

.list-line {
  font-size: 14px;

  &:hover:not(.active) {
    background-color: #eeeeee;
  }
}

</style>